#pragma once

// a level in the game, also known as a board

#include <vector>

#include "tileManager.h"

#include "actor/ill.h"
#include "actor/dog.h"
#include "actor/guard.h"
#include "actor/sg.h"

#include "actor/food.h"
#include "actor/deadBody.h"


// all interactable objects that appear on a board
enum ObjectType {
	OB_ILL,		// illusionist
	OB_GUARD,
	OB_DOG,
	OB_SG,

	OB_FOOD,
	OB_DEADBODY,

	OB_EMPTY,	// nothing there
};


class Board {
private:
	// all boards should have (wxh) of (12x9) to fit in our window
	int width;		// in tiles
	int height;		// in tiles

	// 2-D array of the tiles that comprise the current board
	TILE_TYPE *tiles;

	// the actors
	Ill ill;			// illusionist
	vector<Guard> guards;
	vector<Dog> dogs;
	vector<SG> sgs;

	// the locations of powers
	vector<Food> foods;
	vector<DeadBody> deadBodies;

	// powers, # of uses
	int numFood;
	int numDeadBody;
	int numCloak;
	int numFake;

	// win-loss condition, loss over-rides win
	bool winBit;
	bool loseBit;


	//--- PRIVATE HELPER FUNCTIONS ---//
	void move(int dx, int dy);

public:
	//--- CONSTRUCTORS ---//
	Board(char *filename);
	~Board();

	//--- GETTERS ---//
	int getWidth() {
		return width;
	}

	int getHeight() {
		return height;
	}

	// returns the tile at (i, j)
	TILE_TYPE getTile(int i, int j) {
		assert(i >= 0 && i < width && j >= 0 && j < height);
		return tiles[j*width + i];
	}

	// returns the tile that the actor is standing on
	TILE_TYPE getTile(Actor &a) {
		return getTile(a.x, a.y);
	}

	Ill &getIll() {
		return ill;
	}

	vector<Guard> &getGuards() {
		return guards;
	}

	vector<Dog> &getDogs() {
		return dogs;
	}

	vector<SG> &getSgs() {
		return sgs;
	}

	vector<Food> &getFoods() {
		return foods;
	}

	vector<DeadBody> &getDeadBodies() {
		return deadBodies;
	}

	// returns the object (i.e. actor) at (x, y) and fills in a pointer
	// to that object as an out param
	ObjectType getObject(int x, int y, Actor *(&obj));


	//--- BOUNDS CHECK ---//
	bool inBounds(int x, int y) {
		return x >= 0 && x < width && y >= 0 && y < height;
	}


	//--- ILLUSIONIST MOVEMENT ---//
	void moveUp();
	void moveDown();
	void moveLeft();
	void moveRight();

	//--- ILLUSIONIST POWERS ---//
	void useFood();
	void useDeadBody();
	void useCloak();
	void useFake();
	int getFoodUse() {		// uses remaining
		return numFood;
	}
	int getDeadBodyUse() {	// uses remaining
		return numDeadBody;
	}
	int getCloakUse() {		// uses remaining
		return numCloak;
	}
	int getFakeUse() {		// uses remaining
		return numFake;
	}
	int getIllLives()
	{
		return ill.getLives();
	}
	void setIllLives(int illLives)
	{
		ill.setLives(illLives);
	}

	//--- BOARD STATE ---//
	void checkForWin();
	bool hasLost();
	bool hasWon();
	void setLose();
	void resetWinLoss();
};


void initBoards();

Board *getCurrentBoard();

void loadCurrBoard(int illLives);

void loadNextBoard();

void loadInitialBoard();

// end of board.h
